﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Model.Interfaces;

namespace Model
{
    public static class AdamsSolutionMethod
    {
        private static void Recalculate(IEquation equation, ref double xk, ref double yk, double xPrev, double yPrev, double step)
        {
            yk += step*(1.5*equation.Calculate(xk, yk) - 0.5*equation.Calculate(xPrev, yPrev));
            xk += step;
        }

        /// <summary>
        /// To get some first points, use Runge-Kutt method
        /// </summary>
        /// <param name="system"></param>
        /// <param name="step"></param>
        /// <returns></returns>
        public static IEnumerable<Point> Calculate(this ICauchySystem system, double step)
        {
            if (system == null)
                throw new ArgumentNullException("system");
            if (step <= 0)
                throw new ArgumentException("step");
            // get a count of steps
            var countStep = (int)(Math.Abs(system.B - system.A)/step);
            // create a list of results
            var list = new List<Point>(countStep);
            // get a second point with runge-kutt method
            double x = system.Initial.X, y = system.Initial.Y;
            SolutionMethod.RecalculateRungeKutt(system.Equation, ref x, ref y, step);
            // now, x and y contains the coordinates of the second point
            // set a varibles for the cycle
            list.Add(system.Initial);
            list.Add(new Point(x, y));
            double xk = x, yk = y, xPrev = system.Initial.X, yPrev = system.Initial.Y;
            var prevPoint = new Point();
            // cycle
            for (int i = 1; i < countStep; i++)
            {
                prevPoint.X = xk;
                prevPoint.Y = yk;
                Recalculate(system.Equation, ref xk, ref yk, xPrev, yPrev, step);
                list.Add(new Point(xk, yk));
                xPrev = prevPoint.X;
                yPrev = prevPoint.Y;
            }
            return list;
        }


    }
}
